package com.lifesting.tool.j2as3.visitor;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.util.IModifierConstants;

public class SubTypeVisitor extends ASTVisitor {
	protected Stack<TypeDeclaration> typeStack = new Stack<TypeDeclaration>();
	public static class SubTypeDescriptor{
		String hostType;
		boolean isStatic;
		boolean isInterface;
		String realTypeName;
		int depth;
		@Override
		public String toString() {
			return realTypeName+", static: "+isStatic + ", interface: "+isInterface+" in "+hostType;
		}
	}
	private HashMap<String, SubTypeDescriptor> subTypes = new HashMap<String, SubTypeDescriptor>();
	public Map<String, SubTypeDescriptor> getSubTypes() {
		return Collections.<String,SubTypeDescriptor>unmodifiableMap(subTypes);
	}
	private CompilationUnit unit;
	@Override
	public void endVisit(CompilationUnit node) {
		typeStack.clear();
		unit = null;
	}
	@Override
	public void endVisit(TypeDeclaration node) {
		typeStack.pop();
	}
	@Override
	public boolean visit(CompilationUnit node) {
		unit = node;
		for (Object o : node.types())
			((TypeDeclaration)o).accept(this);
		return false;
	}
	@Override
	public boolean visit(TypeDeclaration node) {
		typeStack.push(node);
		if (typeStack.size() > 1){
		
			StringBuffer sb = new StringBuffer();
			sb.append(unit.getPackage().getName().getFullyQualifiedName());
			String host_type_qn = sb.toString();
			String real_name = "";
			for (int i = 0; i < typeStack.size(); i++){
				String fqn = typeStack.get(i).getName().getIdentifier();
				sb.append('.').append(fqn);
				real_name += fqn+"_";
			}
			int flag = node.getModifiers();
			SubTypeDescriptor desc = new SubTypeDescriptor();
			desc.hostType = host_type_qn;
			desc.isInterface = node.isInterface();
			desc.isStatic= (flag & IModifierConstants.ACC_STATIC) != 0;
			desc.realTypeName = real_name;
			desc.depth = typeStack.size();
			subTypes.put(sb.toString(), desc);
		}
		List bodys = node.bodyDeclarations();
		for (Object o : bodys){
			if (o instanceof TypeDeclaration){
				((TypeDeclaration)o).accept(this);
			}
		}
		return false;
	}
	public void reset() {
		subTypes.clear();
		
	}
	
	
}
